package se.mushroomwars.network;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;

import se.mushroomwars.network.protocol.ReadData;
import se.mushroomwars.network.protocol.SendData;

public class Client extends Listener implements Runnable {
	private SocketChannel client;
	private InetSocketAddress isa;
	private String address;
	private int port;

	private ReadData reader;
	private SendData sender;

	/*
	 * public static void main(String argv[]) throws IOException { Client test =
	 * new Client(); test.connect("192.168.0.15", 50045); }
	 */

	public void run() {
		try {
			connect(address, port);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("couldnt connect to the server");
		}
		System.exit(0);
	}

	public Client(String address, int port) {
		this.port = port;
		this.address = address;
		reader = new ReadData();
		sender = new SendData();
		//extended from Listener
		listener = new ArrayList<DataHandleListener>();
	}

	public void connect(String address, int port) throws IOException {
		client = SocketChannel.open();
		isa = new InetSocketAddress(address, port);
		Selector sel = Selector.open();

		client.configureBlocking(false);
		client.connect(isa);
		// Record to selector (OP_CONNECT type)
		client.register(sel, SelectionKey.OP_CONNECT | SelectionKey.OP_READ
				| SelectionKey.OP_WRITE);

		// wait 500 ms for the server
		while (sel.select(500) > 0) {
			// Get keys
			Set<SelectionKey> keys = sel.selectedKeys();
			Iterator<SelectionKey> itr = keys.iterator();

			while (itr.hasNext()) {
				SelectionKey key = (SelectionKey) itr.next();

				// Remove the current key
				itr.remove();

				// Attempt a connection
				if (key.isConnectable()) {
					// Connection OK
					System.out.println("Connected to: " + isa.getHostName()
							+ " on port: " + isa.getPort());
					// Close pendent connections
					if (client.isConnectionPending())
						client.finishConnect();
				}

				else if (key.isReadable()) {
					Object dataPackage = null;
					try {
						dataPackage = reader.read(client);
						// something went wrong with the client, disconnect the
						// client
					} catch (Exception e) {
						disconnect(client);
					}

					if (dataPackage != null) {
						notifyListener(null, dataPackage,
								reader.getPackageID(client));
					}
				}

				else if (key.isWritable()) {
					if(!sendToServer())
						disconnect(client); //socket error, disconnect
				}
			}
		}
	}
	
	public boolean sendToServer() throws IOException {
		return sender.send(client);
	}
	
	public boolean sendToServer(Object data, int packageID) {
		return sender.send(client, data, packageID);
	}

	private void disconnect(SocketChannel socket) {
		try {
			socket.close();
			System.out.println("Socket closed");
		} catch (IOException e) {
		}
	}
}